package com.example.myapplication.model.https;

import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;

import com.example.myapplication.api.ApiConstants;
import com.example.myapplication.api.ApiServices;
import com.example.myapplication.api.HostType;
import com.example.myapplication.app.App;
import com.example.myapplication.model.UploadListener.NetProgressInterceptor;
import com.example.myapplication.model.UploadListener.ProgressListener;
import com.example.myapplication.utils.LogUtils;
import com.example.myapplication.utils.NetWorkUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by yin97 on 2017/4/4.
 */

public class RetrofitHelpers {
    //读超时长，单位：毫秒
    public static final int READ_TIME_OUT = 7676;
    //连接时长，单位：毫秒
    public static final int CONNECT_TIME_OUT = 7676;

    /* 网络 ->  为了用静态，避免资源回收 */
    private static List<ProgressListener> mNetProgressListeners = new ArrayList<>();

    /**
     * 多少种Host类型
     */

    private static SparseArray<RetrofitHelpers> sRetrofitManager = new SparseArray<>(HostType.TYPE_COUNT);

    //当前正在下载的队列数量
    private static int mCurrentDownloadCount;
    /*下载超时-默认30秒*/
    int Down_Connection_Time = 30;

    /* 头部参数 */
    NetRequestParamsListener mNetRequestParamsListener;
    /*************************缓存设置*********************/
/*
   1. noCache 不使用缓存，全部走网络

    2. noStore 不使用缓存，也不存储缓存

    3. onlyIfCached 只使用缓存

    4. maxAge 设置最大失效时间，失效则不使用 需要服务器配合

    5. maxStale 设置最大失效时间，失效则不使用 需要服务器配合 感觉这两个类似 还没怎么弄清楚，清楚的同学欢迎留言

    6. minFresh 设置有效时间，依旧如上

    7. FORCE_NETWORK 只走网络

    8. FORCE_CACHE 只走缓存*/

    /**
     * 设缓存有效期为两天
     */
    private static final long CACHE_STALE_SEC = 60 * 60 * 24 * 2;

    /**
     * 查询缓存的Cache-Control设置，为if-only-cache时只查询缓存而不会请求服务器，max-stale可以配合设置缓存失效时间
     * max-stale 指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值，那么客户机可接收超出超时期指定值之内的响应消息。
     */
    private static final String CACHE_CONTROL_CACHE = "only-if-cached, max-stale=" + CACHE_STALE_SEC;
    /**
     * 查询网络的Cache-Control设置，头部Cache-Control设为max-age=0
     * (假如请求了服务器并在a时刻返回响应结果，则在max-age规定的秒数内，浏览器将不会发送对应的请求到服务器，数据由缓存直接返回)时则不会使用缓存而请求服务器
     */
    private static final String CACHE_CONTROL_AGE = "max-age=0";




    public  ApiServices INSTANCE;
    private Retrofit retrofit;

    public static ApiServices getInstance(int hostType,boolean isDownload) {
        RetrofitHelpers retrofitManager = sRetrofitManager.get(hostType);
        if (retrofitManager == null) {
            synchronized (RetrofitHelpers.class) {
                if (retrofitManager == null) {
                    retrofitManager = new RetrofitHelpers(hostType,isDownload);
                }
            }
        }
        return retrofitManager.INSTANCE;
    }

    private RetrofitHelpers(int hostType,boolean isDownload) {
        Interceptor interceptor = null;
        if (isDownload) {
            //下载
            interceptor = new NetProgressInterceptor((url, readCount, totalCount, done) -> {
                for (int i = 0; i < mNetProgressListeners.size(); i++) {
                    mNetProgressListeners.get(i).onProgress(url, readCount, totalCount, done);
                }
            });
        } else {
            //开启Log
                //非下载
                HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
                    /** 输出日志 */
                    @Override
                    public void log(String message) {
                        Log.e("HttpLog",message);
                    }
                });
                loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                interceptor = loggingInterceptor;

        }
        //开启Log
//        HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor();
//        logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        //缓存
        File cacheFile = new File(App.getInstance().getCacheDir(), "cache");
        Cache cache = new Cache(cacheFile, 1024 * 1024 * 100); //100Mb

        //增加头部信息
        Interceptor headerInterceptor =new Interceptor() {
            @Override
                public Response intercept(Chain chain) throws IOException {
                Request build = chain.request().newBuilder()
                        .addHeader("Content-Type", "application/json")
                        .build();
                return chain.proceed(build);
            }
        };

        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        if (isDownload) {
            //下载
            builder.connectTimeout(Down_Connection_Time, TimeUnit.SECONDS);
        } else {

                builder.addInterceptor(chain -> {
                    Request.Builder builder1 = chain.request().newBuilder();
                    builder1.addHeader("userId","2745329043").build();
                    return chain.proceed(builder1.build());
                });

            //非下载
            builder.readTimeout(READ_TIME_OUT, TimeUnit.SECONDS);
            builder.connectTimeout(CONNECT_TIME_OUT, TimeUnit.SECONDS);
        }

        //http 网络请求，输出日志监听 debug 才会开启
        if(interceptor != null){
            builder.addInterceptor(interceptor);
        }
                builder.addInterceptor(mRewriteCacheControlInterceptor)
                .addNetworkInterceptor(mRewriteCacheControlInterceptor)
                .addInterceptor(headerInterceptor)
                .addInterceptor(interceptor)
                .cache(cache)
                .build();
        OkHttpClient client = builder.build();
        Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").serializeNulls().create();
         retrofit = new Retrofit.Builder()
                .baseUrl(ApiConstants.getHost(hostType))
                .client(client)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
        INSTANCE=retrofit.create(ApiServices.class);
    }

    /**
     * 云端响应头拦截器，用来配置缓存策略
     * Dangerous interceptor that rewrites the server's cache-control header.
     */
    private final Interceptor mRewriteCacheControlInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            String cacheControl = request.cacheControl().toString();
            if (!NetWorkUtils.isNetConnected(App.getInstance())) {
                request = request.newBuilder()
                        .cacheControl(TextUtils.isEmpty(cacheControl)?CacheControl.FORCE_NETWORK:CacheControl.FORCE_CACHE)
                        .build();
            }
            Response originalResponse = chain.proceed(request);
            if (NetWorkUtils.isNetConnected(App.getInstance())) {
                //有网的时候读接口上的@Headers里的配置，你可以在这里进行统一的设置

                return originalResponse.newBuilder()
                        .header("Cache-Control", cacheControl)
                        .removeHeader("Pragma")
                        .build();
            } else {
                return originalResponse.newBuilder()
                        .header("Cache-Control", "public, only-if-cached, max-stale=" + CACHE_STALE_SEC)
                        .removeHeader("Pragma")
                        .build();
            }
        }
    };

    /**
     * 为OkHttpClient 新增 interceptors
     */
    public  static  void addNetProgressListener(ProgressListener listener) {
        mNetProgressListeners.add(listener);
    }

    /**
     * 为OkHttpClient 移除 interceptors
     */
    public static  void removeNetProgressListener(ProgressListener listener) {
        mNetProgressListeners.remove(listener);
    }
    /** 当前正在下载的任务 */
    public static int getCurrentDownloadCount() {
        return mCurrentDownloadCount;
    }
    /** 新增下载队列  +1 */
    public static void addCurrentDownloadCount() {
        LogUtils.logi("新增下载队列 当前队列数：" + mCurrentDownloadCount);
        mCurrentDownloadCount++;
    }

    /** 移除下载队列 -1 */
    public static  void subCurrentDownloadCount() {
        LogUtils.logi("移除下载队列 当前队列数："+mCurrentDownloadCount);
        mCurrentDownloadCount--;
    }
     /** 配置请求的时候，是否携带 参数，目前只有头部 */

}
